
	/************************************************************************************************

		@API
	 	Factory: jsl.String

		Constructors:
			s			String			(s*)
			s			replicate		(n, s*)

		Slicers:
			s			after				(sel, n*, idx*)
			s			before			(sel, n*, idx*)
			c			last				()
			s			left				(n)
			s			right				(n)

		Info:
			b			contains		(sel, idx*)
			n			index				(sel, n*, idx*)
			a			regexp			(sel, n*, idx*)
			b			endsWith		(sel..)
			b			startsWith	(sel..)
			b			isUpper			()
			b			isLower			()

		Operations:
			n			count				(sel, idx*)
			s			compile			(params..)
			s			inject			(s, idx*)
			s			modify			(sel, s, n*, idx*)
			s			padLeft			(n, c*)
			s			padRight		(n, c*)
			s			reverse			()
			s			trim				()
			s			trimLeft		()
			s			trimRight		()
			s			remove			(sel, n*, idx*)
			s			removeAt		(idx, n*)
			v			reduceRight	(action, value*)

		Cosmetic:
			s 		lower				()
			s 		upper				()

		Legend:
			sel	-> selector -> s | re

	************************************************************************************************/

 	//-------------------------------------------------------------------------------
  jsl.String = function(s) {
 		try {
	   	var proto, rv

			//!
      if(arguments.length > 1)	throw jsl.ParamError()
			//!

			if(arguments.length) {

				if(s instanceof String)
					if(s.__augmented) return s
					else							rv = s
				else
					rv = new String(s)
			}
			else
				rv = new String

			proto = jsl.String.prototype

    	for(var id in proto) rv[id] = proto[id]
    	return rv
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
  }
  //-------------------------------------------------------------------------------
	jsl.String.__name 								= "jsl.String"
	jsl.String.__augmented						= true
  jsl.String.__native								= { replicate: true, __name: true, __augmented: true }
  //-------------------------------------------------------------------------------
	jsl.String.prototype							= jsl.Object()
	jsl.String.prototype.__native 		= jsl.Object.clone(jsl.Object.__native)
	jsl.String.prototype.__name 			= "jsl.String"
	jsl.String.prototype.__augmented	= true
  //-------------------------------------------------------------------------------
  jsl.String.replicate  = function(n, s) {
		try {
			var v, s1

			//!
			if(!arguments.length || arguments.length > 2)	throw jsl.ParamError()
			jsl.validate(n, "i+", "n")
			if(arguments.length === 2)	jsl.validate(s, "s")
			//!

			v 	= new Array(n + 1)
			s1	= arguments.length === 2 ? s + "" : " "

			return v.join(s1)
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
  //-------------------------------------------------------------------------------
  jsl.String.prototype.after = function(sel, n, idx) {
		try {
			var obj

			//!
      if(!jsl.isString(this))												throw jsl.TypeError("BadMethodCall:String")
			if(!arguments.length || arguments.length > 3)	throw jsl.ParamError()
			jsl.validate(sel, "t[re,s+]", "sel")
			if(arguments.length >= 2)											jsl.validate(n, "i!0", "n")
			if(arguments.length === 3) 										jsl.validate(idx, "i+", "idx")//!

			obj = jsl.String.prototype.regexp.apply(this, arguments)

			return obj ? this.slice(obj.index + obj[0].length) : ""
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
  //-------------------------------------------------------------------------------
  jsl.String.prototype.before = function(sel, n, idx) {
		try {
			var i

			//!
      if(!jsl.isString(this))												throw jsl.TypeError("BadMethodCall:String")
			if(!arguments.length || arguments.length > 3)	throw jsl.ParamError()
			jsl.validate(sel, "t[re,s+]", "sel")
			if(arguments.length >= 2)											jsl.validate(n, "i!0", "n")
			if(arguments.length === 3) 										jsl.validate(idx, "i+"	, "idx")//!

			i = jsl.String.prototype.index.apply(this, arguments)

			return i !== -1 ? this.slice(0, i) : this.slice()
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
  //-------------------------------------------------------------------------------
  jsl.String.prototype.last = function() {
		try {
			//!
      if(!jsl.isString(this))		throw jsl.TypeError("BadMethodCall:String")
			if(arguments.length)			throw jsl.ParamError()//!

			return this.length ? this.charAt(this.length - 1) : ""
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
  //-------------------------------------------------------------------------------
  jsl.String.prototype.left = function(n) {
		try {
			//!
      if(!jsl.isString(this))			throw jsl.TypeError("BadMethodCall:String")
			if(arguments.length !== 1) 	throw jsl.ParamError()
			jsl.validate(n, "i", "n")//!

			return this.slice(0, n)
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
  //-------------------------------------------------------------------------------
  jsl.String.prototype.right = function(n) {
		try {
			//!
      if(!jsl.isString(this))			throw jsl.TypeError("BadMethodCall:String")
			if(arguments.length !== 1) 	throw jsl.ParamError()
			jsl.validate(n, "i", "n")//!

			return n != 0 ? this.slice(-n) : []
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
  //-------------------------------------------------------------------------------
  jsl.String.prototype.contains = function(sel, idx) {
		try {
			//!
      if(!jsl.isString(this))												throw jsl.TypeError("BadMethodCall:String")
			if(!arguments.length || arguments.length > 2) throw jsl.ParamError()
			jsl.validate(sel, "t[re,s+]", "sel")
			if(arguments.length === 2) 										jsl.validate(idx, "i+", "idx")//!

			return jsl.String.prototype.index.call(this, sel, 1, idx || 0) !== -1
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
  //-------------------------------------------------------------------------------
  jsl.String.prototype.index = function(sel, n, idx) {
		try {
			var i, ix, rv, s, re, d, fg

			//!
      if(!jsl.isString(this))												throw jsl.TypeError("BadMethodCall:String")
			if(!arguments.length || arguments.length > 3) throw jsl.ParamError()
			jsl.validate(sel, "t[re,s+]", "sel")
			if(arguments.length >= 2 && n != "*") 				jsl.validate(n	, "i!0"	, "n")
			if(arguments.length === 3) 										jsl.validate(idx, "i+"	, "idx")//!

			i 	= +n 		|| 1
			ix	= +idx 	|| 0
			s		= this + ""
			d		= []

			if(sel instanceof RegExp)	{

				fg = +sel.ignoreCase + +sel.multiline + +sel.global
				re = RegExp((sel + "").slice(1, -fg - 1), "g" + (sel.ignoreCase ? "i" : "") + (sel.multiline ? "m" : ""))
			}
			else
				re = RegExp(sel.replace(/[\^\$\.\*\+\?\=\!\:\|\\\/\(\)\[\]\{\}]/g, "\\$&"), "g")

			re.lastIndex = ix

			do {
				rv = re.exec(s)

				if(rv)
					if(i < 0 || n == "*")	d.push(rv.index)
					else if(!--i)					break;

			} while(rv)

			if(i < 0 && d[d.length + i] != null)	rv = d[d.length + i]
			else if(rv)														rv = rv.index

			return n == "*" ? (d.length ? d : null) : (rv != null ? rv : -1)
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
  //-------------------------------------------------------------------------------
  jsl.String.prototype.regexp = function(sel, n, idx) {
		try {
			var i, ix, rv, s, re, d, fg

			//!
      if(!jsl.isString(this))												throw jsl.TypeError("BadMethodCall:String")
			if(!arguments.length || arguments.length > 3) throw jsl.ParamError()
			jsl.validate(sel, "t[re,s+]", "sel")
			if(arguments.length >= 2 && n != "*") 				jsl.validate(n	, "i!0"	, "n")
			if(arguments.length === 3) 										jsl.validate(idx, "i+"	, "idx")//!

			i 	= +n 		|| 1
			ix	= +idx 	|| 0
			s		= this + ""
			d		= []

			if(sel instanceof RegExp) {

				fg = +sel.ignoreCase + +sel.multiline + +sel.global
				re = RegExp((sel + "").slice(1, -fg -1), "g" + (sel.ignoreCase ? "i" : "") + (sel.multiline ? "m" : ""))
			}
			else
				re = RegExp(sel.replace(/[\^\$\.\*\+\?\=\!\:\|\\\/\(\)\[\]\{\}]/g, "\\$&"), "g")

			re.lastIndex = ix

			do {
				rv = re.exec(s)

				if(rv)
					if(i < 0 || n == "*")	d.push(rv)
					else if(!--i)					break;

			} while(rv)

			if(i < 0 && d[d.length + i] != null)
				rv = d[d.length + i]

			return n == "*" ? (d.length ? d : null) : rv
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
  //-------------------------------------------------------------------------------
  jsl.String.prototype.endsWith = function() {
		try {
			var sel, regexp, obj

			//!
	    if(!jsl.isString(this))	throw jsl.TypeError("BadMethodCall:String")
			if(!arguments.length)		throw jsl.ParamError()
			//!

			regexp = jsl.String.prototype.regexp

			for(var a = 0, l = arguments.length; a < l; a++) {

				sel = arguments[a]
				//!
				jsl.validate(sel, "t[re,s+]", "sel[" + a + "]")
				//!

				obj = regexp.call(this, sel, -1)

				if(obj && obj.index + obj[0].length === this.length)
					break
			}

			return a < l
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
  //-------------------------------------------------------------------------------
  jsl.String.prototype.startsWith = function() {
		try {
			var sel

			//!
      if(!jsl.isString(this))	throw jsl.TypeError("BadMethodCall:String")
			if(!arguments.length)		throw jsl.ParamError()
			//!

			for(var a = 0, l = arguments.length; a < l; a++) {

				sel = arguments[a]
				//!
				jsl.validate(sel, "t[re,s+]", "sel[" + sel + "]")
				//!
				if(sel instanceof RegExp ? !this.search(sel) : !this.indexOf(sel))
					break
			}

			return a < l
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
  //-------------------------------------------------------------------------------
  jsl.String.prototype.isUpper = function() {
		try {
			//!
      if(!jsl.isString(this))	throw jsl.TypeError("BadMethodCall:String")
			if(arguments.length)		throw jsl.ParamError()//!
			return this == this.toUpperCase()
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
  //-------------------------------------------------------------------------------
  jsl.String.prototype.isLower = function() {
		try {
			//!
      if(!jsl.isString(this))	throw jsl.TypeError("BadMethodCall:String")
			if(arguments.length)		throw jsl.ParamError()//!
			return this == this.toLowerCase()
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
  //-------------------------------------------------------------------------------
  jsl.String.prototype.count = function(sel, idx) {
		try {
			var ixs

			//!
      if(!jsl.isString(this))												throw jsl.TypeError("BadMethodCall:String")
			if(!arguments.length || arguments.length > 2)	throw jsl.ParamError()
			jsl.validate(sel, "t[re,s+]", "sel")
			if(arguments.length === 2) 										jsl.validate(idx, "i+", "idx")//!

			ixs = jsl.String.prototype.index.call(this, sel, "*", idx || 0)

			return ixs ? ixs.length : 0
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
  //-------------------------------------------------------------------------------
  jsl.String.prototype.compile = function() {
		try {
			var i, args, f

			//!
      if(!jsl.isString(this))		throw jsl.TypeError("BadMethodCall:String")
			if(!arguments.length)			throw jsl.ParamError()//!

			i 		= 0
			args	= arguments
			f			= function(tk, g1, g2) {

				if(g1 && g1.length % 2)					return g1.slice(0, ~~(g1.length / 2)) + "$"
				else if(g1 && i < args.length)	return g1.slice(0, g1.length / 2) 		+ args[i++]
				else if(i < args.length)  			return (g2 || "") + args[i++]
				else														return tk
			}

			return this.replace(/(?:^|(!+)|([^!]?))\$/g, f)
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
  //-------------------------------------------------------------------------------
  jsl.String.prototype.inject = function(s, idx) {
		try {
			var i

			//!
      if(!jsl.isString(this))												throw jsl.TypeError("BadMethodCall:String")
			if(!arguments.length || arguments.length > 2)	throw jsl.ParamError()
			jsl.validate(s, "s")
			if(arguments.length === 2)										jsl.validate(idx, "i+","idx")//!

			i = arguments.length === 2 ? +idx : this.length
			return this.slice(0, i) + s + this.slice(i)
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
  //-------------------------------------------------------------------------------
  jsl.String.prototype.modify = function(sel, s, n, idx) {
		try {
			var objs, v

			//!
      if(!jsl.isString(this))														throw jsl.TypeError("BadMethodCall:String")
			if(arguments.length < 2 || arguments.length > 4) 	throw jsl.ParamError()
			jsl.validate(sel, "t[re,s+]", "sel")
			jsl.validate(s	, "s"				, "s")
			if(arguments.length >= 3 && n != "*") 						jsl.validate(n	, "i!0"	, "n")
			if(arguments.length === 4)												jsl.validate(idx, "i+"	, "idx")//!

			objs 	= jsl.String.prototype.regexp.call(this, sel, n || 1, idx || 0)
			v 		= this.split("")

			if(objs) {

				objs = n == "*" ? objs : [ objs ]

				for(var a = objs.length - 1; a >= 0; a--)
					v.splice(objs[a].index, objs[a][0].length, s)
			}

			return v.join("")
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
  //-------------------------------------------------------------------------------
  jsl.String.prototype.padLeft = function(n, c) {
		try {
			var v, c1, n1

			//!
      if(!jsl.isString(this))												throw jsl.TypeError("BadMethodCall:String")
			if(!arguments.length || arguments.length > 2)	throw jsl.ParamError()
			jsl.validate(n, "i+", "n")
			if(arguments.length === 2) 										jsl.validate(c, "s+", "c")
			if(arguments.length === 2 && c.length !== 1)	throw jsl.ParamError("BadLength")//!

			v		= this.split("")
			c1 	= c || " "
			n1	= +n

			for(var a = this.length; a < n1; a++)
				v.unshift(c1)

			return v.join("")
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
  //-------------------------------------------------------------------------------
  jsl.String.prototype.padRight = function(n, c) {
		try {
		var v, c1, n1

			//!
      if(!jsl.isString(this))												throw jsl.TypeError("BadMethodCall:String")
			if(!arguments.length || arguments.length > 2)	throw jsl.ParamError()
			jsl.validate(n, "i+", "n")
			if(arguments.length === 2) 										jsl.validate(c, "s+", "c")
			if(arguments.length === 2 && c.length !== 1)	throw jsl.ParamError("BadLength")//!

			v		= this.split("")
			c1 	= c || " "
			n1	= +n

			for(var a = this.length; a < n1; a++)
				v.push(c1)

			return v.join("")
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
  //-------------------------------------------------------------------------------
  jsl.String.prototype.reverse = function() {
		try {
			//!
      if(!jsl.isString(this))	throw jsl.TypeError("BadMethodCall:String")
			if(arguments.length)		throw jsl.ParamError()//!

			return this.split("").reverse().join("")
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
  //-------------------------------------------------------------------------------
  jsl.String.prototype.trim = function() {
		try {
			//!
      if(!jsl.isString(this))	throw jsl.TypeError("BadMethodCall:String")
			if(arguments.length)		throw jsl.ParamError()//!

			return this.replace(/^\s+|\s+$/g, "")
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
  //-------------------------------------------------------------------------------
  jsl.String.prototype.trimLeft = function() {
		try {
			//!
      if(!jsl.isString(this))	throw jsl.TypeError("BadMethodCall:String")
			if(arguments.length)		throw jsl.ParamError()//!

			return this.replace(/^\s+/, "")
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
  //-------------------------------------------------------------------------------
  jsl.String.prototype.trimRight = function() {
		try {
			//!
      if(!jsl.isString(this))	throw jsl.TypeError("BadMethodCall:String")
			if(arguments.length)		throw jsl.ParamError()//!

			return this.replace(/\s+$/, "")
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
  //-------------------------------------------------------------------------------
  jsl.String.prototype.remove = function(sel, n, idx) {
		try {
			var objs, v

			//!
      if(!jsl.isString(this))												throw jsl.TypeError("BadMethodCall:String")
			if(!arguments.length || arguments.length > 3)	throw jsl.ParamError()
			jsl.validate(sel, "t[re,s+]", "sel")
			if(arguments.length >= 2 && n != "*") 				jsl.validate(n	, "i!0"	, "n")
			if(arguments.length === 3)										jsl.validate(idx, "i+"	, "idx")//!

			objs 	= jsl.String.prototype.regexp.apply(this, arguments)
			v			= this.split("")

			if(objs) {

				objs = n == "*" ? objs : [ objs ]

				for(var a = objs.length - 1; a >= 0; a--)
					v.splice(objs[a].index, objs[a][0].length)
			}

			return v.join("")
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
  //-------------------------------------------------------------------------------
  jsl.String.prototype.removeAt = function(idx, n) {
		try {
			//!
      if(!jsl.isString(this))												throw jsl.TypeError("BadMethodCall:String")
			if(!arguments.length || arguments.length > 2)	throw jsl.ParamError()
			jsl.validate(idx, "i+", "idx")
			if(arguments.length === 2)										jsl.validate(n, "i+", "n")//!

			return this.slice(0, idx) + this.slice(idx + (n || 1))
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
  //-------------------------------------------------------------------------------
  jsl.String.prototype.lower = function() {
		try {
			//!
      if(!jsl.isString(this))	throw jsl.TypeError("BadMethodCall:String")
			if(arguments.length)		throw jsl.ParamError()//!

			return this.toLowerCase()
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
  //-------------------------------------------------------------------------------
  jsl.String.prototype.upper = function() {
		try {
			//!
      if(!jsl.isString(this))	throw jsl.TypeError("BadMethodCall:String")
			if(arguments.length)		throw jsl.ParamError()//!

			return this.toUpperCase()
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
	//overriding
	//-------------------------------------------------------------------------------
	jsl.String.prototype.walk = function(action, obj) {
		try {
			var v, a, l, ls//!
			if(!arguments.length || arguments.length > 2)	throw jsl.ParamError()
			jsl.validate(action, "f", "action")
			if(arguments.length === 2)	jsl.validate(obj, "o", "obj")//!

			try {
				ls = this.split("")
				for(a = 0, l = ls.length; a < l; a++)
					if((v = obj ? action.call(obj, ls[a], a, this)
											: action(ls[a], a, this)) !== undefined)
						break
			}
			catch(e) {
				throw jsl.ParamError("BadScript:action", e)
			}

			return v
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
  //-------------------------------------------------------------------------------
  jsl.String.prototype.iterator = function() {
    try {
    	var it//!
      if(arguments.length)	throw jsl.ParamError()//!

			it	= { __name: "StringIterator", __ix: 0, __data: this.split("") }

  		//-------------------------------------------------------------------------------
			it.hasNext = function() {
				try {//!
					if(arguments.length)	throw jsl.ParamError()//!
					return this.__ix < this.__data.length
				}
				catch(e) {
					jsl.throwError(e, this, arguments)
				}
			}
  		//-------------------------------------------------------------------------------
			it.next = function() {
				try {//!
					if(arguments.length) 									throw jsl.ParamError()
					if(this.__ix === this.__data.length)	throw jsl.EndOfIterationError()//!

					return this.__data[this.__ix++]
				}
				catch(e) {
					jsl.throwError(e, this, arguments)
				}
			}

      return it
    }
    catch(e) {
      jsl.throwError(e, this, arguments)
    }
  }
	//-------------------------------------------------------------------------------
	jsl.String.prototype.map = function(rule, obj) {
		try {
			var obj2//!
			if(!arguments.length || arguments.length > 2)	throw jsl.ParamError()
			jsl.validate(rule, "f", "rule")
			if(arguments.length === 2)	jsl.validate(obj, "o", "obj")//!

			obj2 = []
			jsl.String.prototype.walk.call(this, function(v, id, obj) {
				obj2[id] = rule.apply(this, arguments)
			}, obj || jsl.__go)

			return obj2.join("")
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
	//-------------------------------------------------------------------------------
	jsl.String.prototype.filter = function(rule, obj) {
		try {
			var obj2//!
			if(!arguments.length || arguments.length > 2)	throw jsl.ParamError()
			jsl.validate(rule, "f", "rule")
			if(arguments.length === 2)	jsl.validate(obj, "o", "obj")//!

			obj2 = []
			jsl.String.prototype.walk.call(this, function(v, id, obj) {
				if(rule.apply(this, arguments)) obj2[id] = v
			}, obj || jsl.__go)

			return obj2.join("")
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
	//-------------------------------------------------------------------------------
	jsl.String.prototype.some = function(rule, obj) {
		try {
			var b//!
			if(!arguments.length || arguments.length > 2)	throw jsl.ParamError()
			jsl.validate(rule, "f", "rule")
			if(arguments.length === 2)	jsl.validate(obj, "o", "obj")//!

			b = jsl.String.prototype.walk.call(this, function(v, id, obj) {
				if(rule.apply(this, arguments)) return true
			}, obj || jsl.__go)

			return !!b
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
	//-------------------------------------------------------------------------------
	jsl.String.prototype.every = function(rule, obj) {
		try {
			var b//!
			if(!arguments.length || arguments.length > 2)	throw jsl.ParamError()
			jsl.validate(rule, "f", "rule")
			if(arguments.length === 2)	jsl.validate(obj, "o", "obj")//!

			b = jsl.String.prototype.walk.call(this, function(v, id, obj) {
				if(!rule.apply(this, arguments)) return false
			}, obj || jsl.__go)

			return b == null || b
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
	//-------------------------------------------------------------------------------
	jsl.String.prototype.reduce = function(rule,  value) {
		try {
			var acc, i, v0//!
			if(!arguments.length || arguments.length > 2)	throw jsl.ParamError()
			jsl.validate(rule, "f", "rule")//!

			i		= 0
			v0	= arguments.length === 2
			acc = value

			jsl.String.prototype.walk.call(this, function(v, id, obj) {

				if(v0)			acc = rule(acc, v, id, obj)
				else if(i)	acc = rule(acc, v, id, obj)
				else				acc = v

				i++
			})

			//!
			if(!i && arguments.length === 1)	throw jsl.MisuseError()//!
			return acc
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
	//-------------------------------------------------------------------------------
	jsl.String.prototype.reduceRight = function(rule,  value) {
		try {
			var acc, i, l, a, ls//!
			if(!arguments.length || arguments.length > 2)	throw jsl.ParamError()
			jsl.validate(rule, "f", "rule")//!

			i		= 0
			ls	= this.split("")
			a 	= ls.length - arguments.length
			acc = a === ls.length - 1 ? value : ls[a + 1]

			try {
				for(; a >= 0; a--) {
					acc = rule(acc, ls[a], a, this)
					i++
				}
			}
			catch(e) {
				throw jsl.ParamError("BadScript:action", e)
			}

			//!
			if(!i && arguments.length === 1)	throw jsl.MisuseError()//!
			return acc
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}

	//String init
	//-------------------------------------------------------------------------------
	;(function() {
		var prt, Str

		Str = jsl.String
		prt	= Str.prototype

		for(var id in prt) {

			Str.__native[id] = true
			prt.__native[id] = true

			if(typeof prt[id] === "function" && !prt[id].__name) {

				Str[id] = function(obj) {
					try {

						//!
						if(!arguments.length)	throw jsl.ParamError()
						if(obj == null)				throw jsl.ParamError("NullValue:obj")
						//!

						return arguments.callee.__f.apply(obj, Array.prototype.slice.call(arguments, 1))
					}
					catch(e) {
						jsl.throwError(e, this, arguments)
					}
				}

				Str[id].__name	= prt[id].__name = id
				Str[id].__f			= prt[id]
			}
		}
	})()
